<template>
   <div class="app-container">
      <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
         <el-form-item label="名称" prop="keyword">
            <el-input v-model="queryParams.keyword" placeholder="请输入名称" clearable style="width: 200px"
               @keyup.enter="handleQuery" />
         </el-form-item>
         <el-form-item label="系统" prop="systemId">
            <el-select v-model="queryParams.systemId" placeholder="所属系统" clearable style="width: 200px">
               <el-option
                  v-for="system in dataSystemOptions"
                  :key="system.id"
                  :label="system.name"
                  :value="system.id"
               />
            </el-select>
         </el-form-item>
         <el-form-item label="类型" prop="type">
            <el-select v-model="queryParams.type" placeholder="接口类型" clearable style="width: 200px">
               <el-option label="拉取" :value="1" />
               <el-option label="服务" :value="2" />
            </el-select>
         </el-form-item>
         <el-form-item>
            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
         </el-form-item>
      </el-form>

      <el-row :gutter="10" class="mb8">
         <el-col :span="1.5">
            <el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
            <!-- v-hasPermi="['system:menu:add']" -->
         </el-col>
         <el-col :span="1.5">
            <el-button type="primary" plain icon="Delete" @click="handleDeleteBatch">删除</el-button>
         </el-col>
         <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
      </el-row>

      <el-table v-if="refreshTable" v-loading="loading" :data="menuList" row-key="menuId"
         :default-expand-all="isExpandAll" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
         @selection-change="handleSelectionChange">
         <el-table-column type="selection" :selectable="selectable" width="55" />
         <el-table-column prop="name" label="接口名称" show-overflow-tooltip></el-table-column>
         <el-table-column prop="systemId" label="所属系统" width="150">
            <template #default="scope">{{ getSystemNameById(scope.row.systemId) }}</template>
         </el-table-column>
         <el-table-column label="接口类型" align="center" prop="type" width="80">
            <template #default="scope">
               <span v-if="scope.row.type === 1" >拉取</span>
               <span v-if="scope.row.type === 2" >服务</span>
            </template>
         </el-table-column>
         <el-table-column prop="pullStrategy" label="拉取方式" width="80"></el-table-column>
         <el-table-column prop="url" label="Url" show-overflow-tooltip></el-table-column>
         <el-table-column label="操作" fixed="right" align="center" width="400" class-name="small-padding fixed-width">
            <template #default="scope">
               <el-button link type="primary" icon="View" @click="handleView(scope.row)">查看</el-button>
               <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
               <el-button v-if="scope.row.parentId != 0" link type="primary" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
               <el-button link type="primary" icon="Box" @click="viewDecode(scope.row.id, scope.row.systemId)">解析包</el-button>
               <el-button link type="primary" icon="Refresh" @click="clearCache(scope.row)">清除缓存</el-button>
            </template>
         </el-table-column>
      </el-table>
      <pagination
         v-show="total > 0"
         :total="total"
         v-model:page="queryParams.pageNum"
         v-model:limit="queryParams.pageSize"
         @pagination="getList"
      />
      <el-dialog :title="title" v-model="open" width="800" append-to-body :before-close="cancel">
         <el-steps style="margin-bottom: 30px; padding: 0 40px;" :active="editStep" finish-status="process">
            <el-step v-for="i in 5" :key="i" @click="switchEditStep(i - 1)" style="cursor: pointer;"/>
          </el-steps>
         <el-form ref="editRef" :model="form" :rules="rules" label-width="70px">
            <!-- step 1 -->
            <template v-if="editStep === 0">
               <el-row :gutter="10">
                  <el-col :span="12">
                     <el-form-item label="接口名称" prop="name" label-width="auto">
                        <el-input v-model="form.name" placeholder="请输入接口名称" />
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="接口编码" prop="code" label-width="auto">
                        <el-input v-model="form.code" placeholder="请输入接口编码" />
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="接口类型" prop="type" label-width="auto">
                        <el-select v-model="form.type" placeholder="接口类型" clearable>
                           <el-option label="拉取" :value="1" />
                           <el-option label="服务" :value="2" />
                        </el-select>
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="系统" prop="systemId" label-width="auto">
                        <el-select v-model="form.systemId" placeholder="所属系统" clearable @change="handleSystemChange">
                           <el-option
                              v-for="system in dataSystemOptions"
                              :key="system.id"
                              :label="system.name"
                              :value="system.id"
                           />
                        </el-select>
                     </el-form-item>
                  </el-col>
                  <el-col :span="24">
                     <el-form-item label="接口描述" prop="description">
                        <el-input type="textarea" resize="none" rows="3" v-model="form.description" placeholder="请输入接口描述" />
                     </el-form-item>
                  </el-col>
                  <el-col :span="24">
                     <el-form-item label="URL" prop="url">
                        <el-input v-model="form.url" placeholder="请输入URL(ip+port+uri)" />
                     </el-form-item>
                  </el-col>
                  <el-col :span="24">
                     <el-row class="edit-list header" :gutter="10">
                        <el-col :span="2"></el-col>
                        <el-col :span="7" style="text-align: center;">请求字段名</el-col>
                        <el-col :span="6" style="text-align: center;">取值参数名</el-col>
                        <el-col :span="6" style="text-align: center;">固定值</el-col>
                        <el-col :span="2"></el-col>
                     </el-row>
                     <el-form-item prop="header" label-width="0">
                        <div class="list">
                           <el-row class="edit-list content" :gutter="10" v-for="param, index in form.uriParam" :key="index">
                              <el-col :span="3">
                                 <span v-if="index === 0" style="font-weight: bold;">URI参数</span>
                              </el-col>
                              <el-col :span="6">
                                 <el-form-item :prop="'uriParam.' + index + '.sourceField'" :rules="rules.columnSourceField">
                                    <el-input v-model="param.sourceField" placeholder="请输入请求字段名" />
                                 </el-form-item>
                              </el-col>
                              <el-col :span="12">
                                 <el-form-item
                                    :prop="'uriParam.' + index + '.targetField'"
                                    :rules="[{
                                       validator: (rule, value, cb) => columnDataValidator(rule, value, cb, param) ,
                                       trigger: 'change'
                                    }]">
                                    <el-row :gutter="10">
                                       <el-col :span="12">
                                             <el-input v-model="param.targetField" placeholder="请输入取值参数名" />
                                       </el-col>
                                       <el-col :span="12">
                                             <el-input v-model="param.value" placeholder="默认值" />
                                       </el-col>
                                    </el-row>
                                 </el-form-item>
                              </el-col>
                              <el-col :span="2" style="justify-content: flex-start;">
                                 <el-button
                                    link
                                    type="danger"
                                    icon="Minus"
                                    @click="toggleParam('minus', index, 'uri')"
                                 ></el-button>
                                 <el-button
                                    v-if="index === form.uriParam.length - 1"
                                    link
                                    type="primary"
                                    icon="Plus"
                                    @click="toggleParam('add', index, 'uri')"
                                 ></el-button>
                              </el-col>
                           </el-row>
                           <el-row class="edit-list content" :gutter="10" v-if="!form.uriParam?.length">
                              <el-col :span="3" style="font-weight: bold;">URI参数</el-col>
                              <el-col :span="18" style="color: gray;">暂无数据</el-col>
                              <el-col :span="2">
                                 <el-button link type="primary" icon="Plus" @click="toggleParam('add', 0, 'uri')"/>
                              </el-col>
                           </el-row>
                        </div>
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="拉取方式" prop="pullStrategy" label-width="auto">
                        <el-select v-model="form.pullStrategy" placeholder="拉取方式" clearable>
                           <el-option label="GET" value="GET" />
                           <el-option label="POST" value="POST" />
                        </el-select>
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="超时时间(毫秒)" prop="timeout" label-width="110">
                        <el-input-number
                           type="number"
                           :min="0"
                           controls-position="none"
                           :step="1"
                           step-strictly
                           v-model="form.timeout"
                           placeholder="请输入超时时间"
                           style="width: auto;"
                        />
                     </el-form-item>
                  </el-col>
                  <el-col :span="24" style="display: flex;">
                     <el-form-item label="限流" prop="limiterFrequency" label-width="77px">
                        <el-input-number
                           type="number"
                           :min="0"
                           controls-position="none"
                           :step="1"
                           step-strictly
                           v-model="form.limiterFrequency"
                           placeholder="限流次数"
                           style="width: 170px"
                        />
                        &nbsp;&nbsp;/&nbsp;&nbsp;
                     </el-form-item>
                     <el-form-item prop="limiterUnit" label-width="0">
                        <el-select v-model="form.limiterUnit" placeholder="时间单位" clearable style="width: 120px">
                           <el-option label="分钟" value="MINUTES" />
                           <el-option label="小时" value="HOURS" />
                           <el-option label="天" value="DAYS" />
                        </el-select>
                     </el-form-item>
                  </el-col>
               </el-row>
            </template>
            <!-- step 2 -->
            <template v-if="editStep === 1">
               <el-row class="edit-list header" :gutter="10">
                  <el-col :span="2"></el-col>
                  <el-col :span="7" style="text-align: center;">请求字段名</el-col>
                  <el-col :span="6" style="text-align: center;">取值参数名</el-col>
                  <el-col :span="6" style="text-align: center;">固定值</el-col>
                  <el-col :span="2"></el-col>
               </el-row>
               <el-row>
                  <div class="list">
                     <el-row class="edit-list content" :gutter="10" v-for="h, index in form.header" :key="index">
                        <el-col :span="2">
                           <span v-if="index === 0" style="font-weight: bold; margin-bottom: 18px;">请求头</span>
                        </el-col>
                        <el-col :span="7">
                           <el-form-item :prop="'header.' + index + '.sourceField'" :rules="rules.columnSourceField">
                              <el-input v-model="h.sourceField" placeholder="请输入请求字段名" />
                           </el-form-item>
                        </el-col>
                        <el-col :span="12">
                           <el-form-item
                              :prop="'header.' + index + '.targetField'"
                              :rules="[{
                                 validator: (rule, value, cb) => columnDataValidator(rule, value, cb, h) ,
                                 trigger: 'change'
                              }]">
                              <el-row :gutter="10" style="height: auto;">
                                 <el-col :span="12">
                                       <el-input v-model="h.targetField" placeholder="请输入取值参数名" />
                                 </el-col>
                                 <el-col :span="12">
                                       <el-input v-model="h.value" placeholder="默认值" />
                                 </el-col>
                              </el-row>
                           </el-form-item>
                        </el-col>
                        <el-col :span="2" style="justify-content: flex-start;">
                           <el-button
                              link
                              type="danger"
                              icon="Minus"
                              @click="toggleParam('minus', index, 'header')"
                              style="margin-bottom: 18px;"
                           ></el-button>
                           <el-button
                              v-if="index === form.header.length - 1"
                              link
                              type="primary"
                              icon="Plus"
                              @click="toggleParam('add', index, 'header')"
                              style="margin-bottom: 18px;"
                           ></el-button>
                        </el-col>
                     </el-row>
                     <el-row class="edit-list content" :gutter="10" v-if="!form.header?.length">
                        <el-col :span="2" style="font-weight: bold;">请求头</el-col>
                        <el-col :span="19" style="color: gray;">暂无数据</el-col>
                        <el-col :span="2">
                           <el-button link type="primary" icon="Plus" @click="toggleParam('add', 0, 'header')"/>
                        </el-col>
                     </el-row>
                  </div>
               </el-row>
               <el-row>
                  <el-form-item prop="header" label="请求体" label-width="58px">
                     <json-editor-vue
                        style="width: 620px; height: 300px;"
                        v-model="reqJsonObj"
                        language="zh-CN"
                        currentMode="code"
                        :modeList="['view', 'code']"
                        @update:modelValue="jsonEditorUpdate('req')"
                        @validationError="(editor, err) => jsonEditorError(editor, err, 'req')"
                        :options="jsonEditorOptions"
                     />
                  </el-form-item>
               </el-row>
               <el-row :gutter="10">
                  <el-col :span="12">
                     <el-form-item label="是否循环调用" prop="isLoop" label-width="125">
                        <el-select v-model="form.isLoop" placeholder="是否循环调用" clearable>
                           <el-option label="是" :value="1" />
                           <el-option label="否" :value="0" />
                        </el-select>
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="循环参数路径" prop="loopPath" label-width="140">
                        <el-input v-model="form.loopPath" placeholder="请输入循环参数路径" />
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="请求分页字段路径" prop="pageNo" label-width="125">
                        <el-input v-model="form.pageNo" placeholder="请输入请求分页字段路径" />
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="请求响应状态值路径" prop="respStatus" label-width="140">
                        <el-input v-model="form.respStatus" placeholder="请输入请求响应状态值路径" />
                     </el-form-item>
                  </el-col>
               </el-row>
            </template>
            <!-- step 3 -->
            <template v-if="editStep === 2">
               <el-row :gutter="10">
                  <el-col :span="12">
                     <el-form-item label="响应成功状态值" prop="respSuccessVal" label-width="125">
                        <el-input v-model="form.respSuccessVal" placeholder="请输入响应成功状态值" />
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="响应页数字段路径" prop="respPageCount" label-width="140">
                        <el-input v-model="form.respPageCount" placeholder="请输入响应页数字段路径" />
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="响应数据字段路径" prop="respBody" label-width="125">
                        <el-input v-model="form.respBody" placeholder="请输入响应数据字段路径" />
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="结果集存储Key" prop="resultKey" label-width="140">
                        <el-input v-model="form.resultKey" placeholder="请输入结果集存储Key" />
                     </el-form-item>
                  </el-col>
               </el-row>
               <el-row>
                  <el-form-item prop="header" label="返回体" label-width="58px">
                     <json-editor-vue
                        style="width: 620px; height: 400px;"
                        v-model="resJsonObj"
                        language="zh-CN"
                        currentMode="code"
                        :modeList="['view', 'code']"
                        @update:modelValue="jsonEditorUpdate('res')"
                        @validationError="(editor, err) => jsonEditorError(editor, err, 'res')"
                        :options="jsonEditorOptions"
                     />
                  </el-form-item>
               </el-row>
            </template>
            <!-- step 4 -->
            <template v-if="editStep === 3">
               <el-row>
                  <el-col :span="12">
                     <el-form-item label="物模型" prop="dynamicTableId" label-width="auto">
                        <el-select v-model="form.dynamicTableId" placeholder="请选择" clearable @change="handleModelChange">
                           <el-option
                              v-for="model in objectModelOptions"
                              :key="model.id"
                              :label="model.name"
                              :value="model.id"
                           />
                        </el-select>
                     </el-form-item>
                  </el-col>
               </el-row>
               
               <el-row class="edit-list header" :gutter="4">
                  <el-col :span="3">
                     <el-upload
                        v-loading="uploading"
                        :on-change="importFile"
                        :limit="1"
                        :show-file-list="false"
                        :auto-upload="false"
                        ref="fileUpload"
                     >
                        <el-button type="primary" style="padding: 3px 5px;">导入</el-button>
                     </el-upload>
                     <a style="color: #409EFF; margin-left: 8px; font-size: 14px; width: fit-content;" @click="downloadTemplate">模板</a>
                  </el-col>
                  <el-col :span="3" style="text-align: center;">字段</el-col>
                  <el-col :span="3" style="text-align: center;">字段类型</el-col>
                  <el-col :span="4" style="text-align: center;">物模型属性</el-col>
                  <el-col :span="2" style="text-align: center;">是否保存</el-col>
                  <el-col :span="2" style="text-align: center;">去重唯一字段</el-col>
                  <el-col :span="4" style="text-align: center;">字典类型</el-col>
                  <el-col :span="2"></el-col>
               </el-row>
               <div class="list model">
                  <el-row class="edit-list content" :gutter="4" v-for="item, index in form.fieldCovertMapping" :key="index">
                     <el-col :span="3">
                        <span v-if="index === 0" style="font-weight: bold; margin-bottom: 18px;">物模型转换</span>
                     </el-col>
                     <el-col :span="3">
                        <el-form-item :prop="'fieldCovertMapping.' + index + '.sourceField'" :rules="rules.modelSourceField">
                           <el-input v-model="item.sourceField" placeholder="字段名称" />
                        </el-form-item>
                     </el-col>
                     <el-col :span="3">
                        <el-form-item :prop="'fieldCovertMapping.' + index + '.category'" :rules="rules.category" style="width: 100%;">
                           <el-select v-model="item.category" placeholder="请选择" clearable>
                              <el-option label="普通" :value="1" />
                              <el-option label="字典" :value="2" />
                              <el-option label="文件" :value="3" />
                           </el-select>
                        </el-form-item>
                     </el-col>
                     <el-col :span="4">
                        <el-form-item style="width: 100%;">
                           <el-select
                              v-model="item.targetField"
                              placeholder="请选择"
                              clearable
                              @change="modelFeatureChange(index)">
                              <el-option
                                 v-for="feat in modelFeatureOptions"
                                 :key="feat.name"
                                 :label="feat.name"
                                 :value="feat.name"
                              />
                           </el-select>
                        </el-form-item>
                     </el-col>
                     <el-col :span="2">
                        <el-form-item>
                           <el-checkbox v-model="item.save" :true-value="1" :false-value="0" />
                        </el-form-item>
                     </el-col>
                     <el-col :span="2">
                        <el-form-item>
                           <el-checkbox v-model="item.unique" :true-value="1" :false-value="0" />
                        </el-form-item>
                     </el-col>
                     <el-col :span="4">
                        <el-form-item style="width: 100%;">
                           <el-select v-model="item.dicTypeId" placeholder="字典类型" clearable :disabled="item.category !== 2">
                              <el-option
                                 v-for="type in dictTypeOptions"
                                 :key="type.id"
                                 :label="type.typeName"
                                 :value="type.id"
                              />
                           </el-select>
                        </el-form-item>
                     </el-col>
                     <el-col :span="2" style="justify-content: flex-start;">
                        <el-button
                           link
                           type="danger"
                           icon="Minus"
                           @click="toggleObject('minus', index)"
                           style="margin-bottom: 18px;"
                        ></el-button>
                        <el-button
                           v-if="index === form.fieldCovertMapping.length - 1"
                           link
                           type="primary"
                           icon="Plus"
                           @click="toggleObject('add', index)"
                           style="margin-bottom: 18px;"
                        ></el-button>
                     </el-col>
                  </el-row>
                  <el-row class="edit-list content" :gutter="10" v-if="!form.fieldCovertMapping?.length">
                     <el-col :span="3" style="font-weight: bold;">物模型转换</el-col>
                     <el-col :span="18" style="color: gray;">暂无数据</el-col>
                     <el-col :span="2" style="justify-content: flex-start;">
                        <el-button
                           link
                           type="primary"
                           icon="Plus"
                           @click="toggleObject('add', 0)"
                        ></el-button>
                     </el-col>
                  </el-row>
               </div>
               <el-row>
                  <el-col :span="24">
                     <el-form-item label="前置处理器类型" prop="preHandleType" label-width="110">
                        <el-select v-model="form.preHandleType" placeholder="请选择前置处理器类型" clearable style="width: 200px" @change="handleTypeChange('pre')">
                           <el-option label="无" :value="null" />
                           <el-option label="GLUE(JAVA)" value="GLUE_JAVA" />
                           <el-option label="JAR" value="JAR" />
                        </el-select>
                     </el-form-item>
                  </el-col>
                  <el-col :span="24" v-show="form.preHandleType === 'GLUE_JAVA'">
                     <el-form-item label="前置处理器" prop="preHandle" label-width="110">
                        <el-input type="textarea" resize="none" rows="3" v-model="form.preHandle" placeholder="请输入前置处理器" />
                     </el-form-item>
                  </el-col>
                  <el-col :span="24" v-show="form.preHandleType === 'JAR'">
                     <el-form-item label="前置JAR包" prop="preHandle" label-width="110">
                        <el-upload
                           v-loading="preHandleUploading"
                           :on-change="(file) => importJarFile(file, 'pre')"
                           :limit="1"
                           :show-file-list="false"
                           :auto-upload="false"
                           ref="preHandleFileUpload"
                        >
                           <el-button type="primary">上传JAR</el-button>
                        </el-upload>
                        <span style="margin-left: 10px;">{{ form.preHandleJarName || form.preHandleJarUrl }}</span>
                     </el-form-item>
                  </el-col>
                  <el-col :span="24">
                     <el-form-item label="后置处理器类型" prop="postHandleType" label-width="110">
                        <el-select v-model="form.postHandleType" placeholder="请选择后置处理器类型" clearable style="width: 200px" @change="handleTypeChange('post')">
                           <el-option label="无" :value="null" />
                           <el-option label="GLUE(JAVA)" value="GLUE_JAVA" />
                           <el-option label="JAR" value="JAR" />
                        </el-select>
                     </el-form-item>
                  </el-col>
                  <el-col :span="24" v-show="form.postHandleType === 'GLUE_JAVA'">
                     <el-form-item label="后置处理器" prop="postHandle" label-width="110">
                        <el-input type="textarea" resize="none" rows="3" v-model="form.postHandle" placeholder="请输入前置处理器" />
                     </el-form-item>
                  </el-col>
                  <el-col :span="24" v-show="form.postHandleType === 'JAR'">
                     <el-form-item label="后置JAR包" prop="postHandle" label-width="110">
                        <el-upload
                           v-loading="preHandleUploading"
                           :on-change="(file) => importJarFile(file, 'post')"
                           :limit="1"
                           :show-file-list="false"
                           :auto-upload="false"
                           ref="postHandleFileUpload"
                        >
                           <el-button type="primary">上传JAR</el-button>
                        </el-upload>
                        <span style="margin-left: 10px;">{{ form.postHandleJarName || postHandleJarUrl }}</span>
                     </el-form-item>
                  </el-col>
               </el-row>
               <el-row>
                  <el-col :span="9">
                     <el-form-item label="是否缓存结果" prop="isCache" label-width="110">
                        <el-select v-model="form.isCache" placeholder="请选择" clearable style="width: 100px">
                           <el-option label="是" :value="1" />
                           <el-option label="否" :value="0" />
                        </el-select>
                     </el-form-item>
                  </el-col>
                  <el-col :span="10">
                     <el-form-item label="有效缓存时间" prop="effectiveTime" label-width="auto">
                        <el-input-number
                           type="number"
                           :min="0"
                           controls-position="none"
                           :step="1"
                           step-strictly
                           v-model="form.effectiveTime"
                           placeholder="有效缓存时间"
                           style="width: 170px"
                        />
                     </el-form-item>
                  </el-col>
                  <el-col :span="4">
                     <el-form-item prop="timeUnit" label-width="0">
                        <el-select v-model="form.timeUnit" placeholder="时间单位" clearable style="width: 120px">
                           <el-option label="分钟" value="MINUTES" />
                           <el-option label="小时" value="HOURS" />
                           <el-option label="天" value="DAYS" />
                        </el-select>
                     </el-form-item>
                  </el-col>
               </el-row>
               <el-row>
                  <el-col :span="9">
                     <el-form-item label="是否为对象" prop="isObj" label-width="110">
                        <el-select v-model="form.isObj" placeholder="请选择" clearable style="width: 100px">
                           <el-option label="是" :value="1" />
                           <el-option label="否" :value="0" />
                        </el-select>
                     </el-form-item>
                  </el-col>
                  <el-col :span="15">
                     <el-form-item label="结果集是否作为请求参数" prop="asReqParam" label-width="auto">
                        <el-select v-model="form.asReqParam" placeholder="请选择" clearable style="width: 100px">
                           <el-option label="是" :value="1" />
                           <el-option label="否" :value="0" />
                        </el-select>
                     </el-form-item>
                  </el-col>
               </el-row>
               <el-row>
                  <el-col :span="24">
                     <el-row class="edit-list header" :gutter="10">
                        <el-col :span="2"></el-col>
                        <el-col :span="7" style="text-align: center;">请求字段名</el-col>
                        <el-col :span="6" style="text-align: center;">取值参数名</el-col>
                        <el-col :span="6" style="text-align: center;">固定值</el-col>
                        <el-col :span="2"></el-col>
                     </el-row>
                     <el-form-item prop="header" label-width="0">
                        <div class="list">
                           <el-row class="edit-list content" :gutter="10" v-for="param, index in form.initParam" :key="index">
                              <el-col :span="3">
                                 <span v-if="index === 0" style="font-weight: bold;">初始参数</span>
                              </el-col>
                              <el-col :span="6">
                                 <el-form-item :prop="'initParam.' + index + '.sourceField'" :rules="rules.columnSourceField">
                                    <el-input v-model="param.sourceField" placeholder="请输入请求字段名" />
                                 </el-form-item>
                              </el-col>
                              <el-col :span="12">
                                 <el-form-item
                                    :prop="'initParam.' + index + '.targetField'"
                                    :rules="[{
                                       validator: (rule, value, cb) => columnDataValidator(rule, value, cb, param) ,
                                       trigger: 'change'
                                    }]">
                                    <el-row :gutter="10">
                                       <el-col :span="12">
                                          <el-input v-model="param.targetField" placeholder="请输入取值参数名" />
                                       </el-col>
                                       <el-col :span="12">
                                          <el-input v-model="param.value" placeholder="默认值" />
                                       </el-col>
                                    </el-row>
                                 </el-form-item>
                              </el-col>
                              <el-col :span="2" style="justify-content: flex-start;">
                                 <el-button
                                    link
                                    type="danger"
                                    icon="Minus"
                                    @click="toggleParam('minus', index, 'init')"
                                 ></el-button>
                                 <el-button
                                    v-if="index === form.initParam.length - 1"
                                    link
                                    type="primary"
                                    icon="Plus"
                                    @click="toggleParam('add', index, 'init')"
                                 ></el-button>
                              </el-col>
                           </el-row>
                           <el-row class="edit-list content" :gutter="10" v-if="!form.initParam?.length">
                              <el-col :span="3" style="font-weight: bold;">初始参数</el-col>
                              <el-col :span="18" style="color: gray;">暂无数据</el-col>
                              <el-col :span="2">
                                 <el-button link type="primary" icon="Plus" @click="toggleParam('add', 0, 'init')"/>
                              </el-col>
                           </el-row>
                        </div>
                     </el-form-item>
                  </el-col>
               </el-row>
            </template>
            <!-- step 5 -->
            <template v-if="editStep === 4">
               <div style="font-weight: bold; margin-bottom: 18px; font-size: 20px;">数据过滤规则：</div>
               <div class="list rule-group">
                  <div class="filter-group-wrapper" v-for="group, index in form.filterGroups" :key="index">
                     <div class="filter-group" :gutter="10">
                        <div class="filter-rule" :style="{ display: 'inline-block'}">
                           <el-row :gutter="10" v-for="(rule, i) in group.filterRules" :key="i">
                              <el-col :span="4" :style="i === 0 ? { display: 'flex', alignItems: 'center', justifyContent: 'center'} : {}">
                                 <span v-if="i === 0" style="font-weight: bold; margin-bottom: 18px;">条件组{{index + 1}}</span>
                                 <el-form-item v-else :prop="'filterGroups.' + index + '.filterRules.' + i + '.operate'" :rules="rules.chooseRule" :style="{ marginLeft: '10px'}">
                                    <el-select v-model="rule.operate" placeholder="请选择" clearable>
                                       <el-option label="并且" value="并且" />
                                       <el-option label="或者" value="或者" />
                                    </el-select>
                                 </el-form-item>
                              </el-col>
                              <el-col :span="6">
                                 <el-form-item :prop="'filterGroups.' + index + '.filterRules.' + i + '.fieldName'" :rules="rules.category">
                                    <el-select v-model="rule.fieldName" placeholder="请选择" clearable>
                                       <el-option
                                          v-for="feat in modelFeatureOptions"
                                          :key="feat.name"
                                          :label="feat.name"
                                          :value="feat.name"
                                       />
                                    </el-select>
                                 </el-form-item>
                              </el-col>
                              <el-col :span="4">
                                 <el-form-item :prop="'filterGroups.' + index + '.filterRules.' + i + '.symbolDicId'" :rules="rules.chooseRule">
                                    <el-select v-model="rule.symbolDicId" placeholder="请选择" clearable>
                                       <el-option v-for="item in symbolOptions" :label="item.name" :value="item.id" />
                                    </el-select>
                                 </el-form-item>
                              </el-col>
                              <el-col :span="7">
                                 <el-form-item :prop="'filterGroups.' + index + '.filterRules.' + i + '.inputVal'" :rules="rules.inputVal">
                                    <el-input v-model="rule.inputVal" placeholder="输入值" />
                                 </el-form-item>
                              </el-col>
                              <el-col :span="3" :style="{ display: 'flex', alignItems: 'center', justifyContent: 'flex-start'}">
                                 <el-button
                                    link
                                    type="danger"
                                    icon="Minus"
                                    @click="toggleRule('minus', index, i)"
                                    style="margin-bottom: 18px;"
                                 ></el-button>
                                 <el-button
                                    v-if="i === form.filterGroups[index].filterRules.length - 1"
                                    link
                                    type="primary"
                                    icon="Plus"
                                    @click="toggleRule('add', index, i)"
                                    style="margin-bottom: 18px;"
                                 ></el-button>
                              </el-col>
                           </el-row>
                        </div>
                        <div class="filter-group-btn">
                           <el-button
                              link
                              type="danger"
                              icon="Minus"
                              @click="toggleRule('minus', index)"
                           ></el-button>
                           <el-button
                              v-if="index === form.filterGroups.length - 1"
                              link
                              type="primary"
                              icon="Plus"
                              @click="toggleRule('add', index)"
                           ></el-button>
                        </div>
                     </div>
                     <div class="mid-operate" v-if="index < form.filterGroups.length - 1">
                        <el-form-item :prop="'filterGroups.' + index + '.operate'" :rules="rules.chooseRule">
                           <el-select v-model="group.operate" placeholder="请选择" clearable>
                              <el-option label="并且" value="并且" />
                              <el-option label="或者" value="或者" />
                           </el-select>
                        </el-form-item>
                     </div>
                  </div>
                  <el-row class="edit-list content" :gutter="10" v-if="!form.filterGroups?.length">
                     <el-col :span="3" style="font-weight: bold;">条件组</el-col>
                     <el-col :span="18" style="color: gray;">暂无数据</el-col>
                     <el-col :span="2" style="justify-content: flex-start;">
                        <el-button
                           link
                           type="primary"
                           icon="Plus"
                           @click="toggleRule('add', 0)"
                        ></el-button>
                     </el-col>
                  </el-row>
               </div>
            </template>
         </el-form>
         <template #footer>
            <div class="dialog-footer">
               <el-button v-show="editStep > 0" @click="switchEditStep(editStep - 1)">上一步</el-button>
               <el-button v-show="editStep < 4" type="primary" @click="switchEditStep(editStep + 1)">下一步</el-button>
               <el-button v-show="editStep === 4" type="primary" @click="submitForm">提 交</el-button>
               <el-button type="success" @click="saveTemp">存草稿</el-button>
               <el-button @click="cancel">取 消</el-button>
            </div>
         </template>
      </el-dialog>

      <el-dialog title="接口详情" v-model="openDetail" width="800" append-to-body :before-close="cancel">
         <el-steps style="margin-bottom: 30px; padding: 0 40px;" :active="editStep" finish-status="process">
            <el-step v-for="i in 5" :key="i" @click="switchEditStep(i - 1)" style="cursor: pointer;"/>
          </el-steps>
         <el-form label-width="70px">
            <!-- step 1 -->
            <template v-if="editStep === 0">
               <el-row :gutter="10">
                  <el-col :span="8">
                     <el-form-item label="名称" label-width="70">
                        {{ form.name }}
                     </el-form-item>
                  </el-col>
                  <el-col :span="8">
                     <el-form-item label="接口类型" label-width="auto">
                        <span v-if="form.type === 1">拉取</span>
                        <span v-if="form.type === 2">服务</span>
                     </el-form-item>
                  </el-col>
                  <el-col :span="8">
                     <el-form-item label="系统" label-width="auto">
                        {{ dataSystemOptions.find(item => item.id === form.systemId)?.name  || form.systemId}}
                     </el-form-item>
                  </el-col>
                  <el-col :span="24">
                     <el-form-item label="接口描述">
                        {{ form.description }}
                     </el-form-item>
                  </el-col>
                  <el-col :span="24">
                     <el-form-item label="URL">
                        {{ form.url }}
                     </el-form-item>
                  </el-col>
                  <el-col :span="24">
                     <el-row class="edit-list header" :gutter="10">
                        <el-col :span="3"></el-col>
                        <el-col :span="6" style="text-align: center;">请求字段名</el-col>
                        <el-col :span="6" style="text-align: center;">取值参数名</el-col>
                        <el-col :span="6" style="text-align: center;">固定值</el-col>
                     </el-row>
                     <el-form-item prop="header" label-width="0">
                        <div class="list">
                           <el-row class="edit-list content" :gutter="10" v-for="param, index in form.uriParam" :key="index">
                              <el-col :span="3">
                                 <span v-if="index === 0" style="font-weight: bold;">URI参数</span>
                              </el-col>
                              <el-col :span="6">{{ param.sourceField || '-' }}</el-col>
                              <el-col :span="6">{{ param.targetField || '-' }}</el-col>
                              <el-col :span="6">{{ param.value || '-'}}</el-col>
                           </el-row>
                           <el-row class="edit-list content" :gutter="10" v-if="!form.uriParam?.length">
                              <el-col :span="3" style="font-weight: bold;">URI参数</el-col>
                              <el-col :span="18" style="color: gray;">暂无数据</el-col>
                           </el-row>
                        </div>
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="拉取方式" label-width="auto">
                        {{ form.pullStrategy }}
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="超时时间(毫秒)" label-width="110">
                        {{ form.timeout }}
                     </el-form-item>
                  </el-col>
                  <el-col :span="24">
                     <el-form-item label="限流" label-width="68">
                        <span v-if="form.limiterFrequency">
                           {{ form.limiterFrequency }}次
                           <span v-if="form.limiterUnit === 'MINUTES'">/分钟</span>
                           <span v-if="form.limiterUnit === 'HOURS'">/小时</span>
                           <span v-if="form.limiterUnit === 'DAYS'">/天</span>
                        </span>
                        <span v-else>-</span>
                     </el-form-item>
                  </el-col>
               </el-row>
            </template>
            <!-- step 2 -->
            <template v-if="editStep === 1">
               <el-row class="edit-list header" :gutter="10">
                  <el-col :span="2"></el-col>
                  <el-col :span="7" style="text-align: center;">请求字段名</el-col>
                  <el-col :span="6" style="text-align: center;">取值参数名</el-col>
                  <el-col :span="6" style="text-align: center;">固定值</el-col>
               </el-row>
               <el-row>
                  <div class="list">
                     <el-row class="edit-list content" :gutter="10" v-for="h, index in form.header" :key="index">
                        <el-col :span="2">
                           <span v-if="index === 0" style="font-weight: bold;">请求头</span>
                        </el-col>
                        <el-col :span="7">{{ h.sourceField }}</el-col>
                        <el-col :span="6">{{ h.targetField }}</el-col>
                        <el-col :span="6">{{ h.value }}</el-col>
                     </el-row>
                     <el-row class="edit-list content" :gutter="10" v-if="!form.header?.length">
                        <el-col :span="2" style="font-weight: bold;">请求头</el-col>
                        <el-col :span="19" style="color: gray;">暂无数据</el-col>
                     </el-row>
                  </div>
               </el-row>
               <el-row>
                  <el-form-item prop="header" label="请求体" label-width="58px">
                     <json-editor-vue
                        style="width: 620px; height: 300px;"
                        v-model="reqJsonObj"
                        language="zh-CN"
                        currentMode="view"
                        :modeList="['view']"
                        :options="jsonEditorOptions"
                     />
                  </el-form-item>
               </el-row>
               <el-row :gutter="10">
                  <el-col :span="12">
                     <el-form-item label="是否循环调用" prop="isLoop" label-width="125">
                        <span v-if="form.isLoop === 1">是</span>
                        <span v-if="form.isLoop === 0">否</span>
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="循环参数路径" prop="loopPath" label-width="140">
                        {{ form.loopPath }}
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="请求分页字段路径" prop="pageNo" label-width="125">
                        {{ form.pageNo }}
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="请求响应状态值路径" prop="respStatus" label-width="140">
                        {{ form.respStatus }}
                     </el-form-item>
                  </el-col>
               </el-row>
            </template>
            <!-- step 3 -->
            <template v-if="editStep === 2">
               <el-row :gutter="10">
                  <el-col :span="12">
                     <el-form-item label="响应成功状态值" prop="respSuccessVal" label-width="125">
                        {{ form.respSuccessVal || '-' }}
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="响应页数字段路径" prop="respPageCount" label-width="140">
                        {{ form.respPageCount || '-'}}
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="响应数据字段路径" prop="respBody" label-width="125">
                        {{ form.respBody || '-'}}
                     </el-form-item>
                  </el-col>
                  <el-col :span="12">
                     <el-form-item label="结果集存储Key" prop="resultKey" label-width="140">
                        {{ form.resultKey || '-'}}
                     </el-form-item>
                  </el-col>
               </el-row>
               <el-row>
                  <el-form-item prop="header" label="返回体" label-width="58px">
                     <json-editor-vue
                        style="width: 620px; height: 400px;"
                        v-model="resJsonObj"
                        language="zh-CN"
                        currentMode="view"
                        :modeList="['view']"
                        :options="jsonEditorOptions"
                     />
                  </el-form-item>
               </el-row>
            </template>
            <!-- step 4 -->
            <template v-if="editStep === 3">
               <el-row>
                  <el-col :span="12">
                     <el-form-item label="物模型" prop="dynamicTableId" label-width="auto">
                        {{ objectModelOptions.find(item => item.id === form.dynamicTableId)?.name  || form.dynamicTableId}}
                     </el-form-item>
                  </el-col>
               </el-row>
               <el-row class="edit-list header" :gutter="10">
                  <el-col :span="3"></el-col>
                  <el-col :span="4" style="text-align: center;">字段</el-col>
                  <el-col :span="4" style="text-align: center;">物模型属性</el-col>
                  <el-col :span="3" style="text-align: center;">是否保存</el-col>
                  <el-col :span="3" style="text-align: center; white-space: nowrap;">去重唯一字段</el-col>
                  <el-col :span="4" style="text-align: center;">字典类型</el-col>
               </el-row>
               <div class="list model">
                  <el-row class="edit-list content" :gutter="10" v-for="item, index in form.fieldCovertMapping" :key="index">
                     <el-col :span="3">
                        <span v-if="index === 0" style="font-weight: bold;">物模型转换</span>
                     </el-col>
                     <el-col :span="4">{{ item.sourceField }}</el-col>
                     <el-col :span="4">{{ item.targetField }}</el-col>
                     <el-col :span="3">
                        <el-checkbox v-model="item.save" :true-value="1" :false-value="0" disabled />
                     </el-col>
                     <el-col :span="3">
                        <el-checkbox v-model="item.unique" :true-value="1" :false-value="0" disabled />
                     </el-col>
                     <el-col :span="4">
                        {{ dictTypeOptions.find(item => item.id === item.dicTypeId)?.typeName  || '-'}}
                     </el-col>
                  </el-row>
                  <el-row class="edit-list content" :gutter="10" v-if="!form.fieldCovertMapping?.length">
                     <el-col :span="3" style="font-weight: bold;">物模型转换</el-col>
                     <el-col :span="18" style="color: gray;">暂无数据</el-col>
                  </el-row>
               </div>
               <el-row>
                  <el-col :span="24">
                     <el-form-item label="前置处理器类型" prop="preHandleType" label-width="110">
                        {{ form.preHandleType || '无'}}
                     </el-form-item>
                  </el-col>
                  <el-col :span="24" v-show="form.preHandleType === 'GLUE_JAVA'">
                     <el-form-item label="前置处理器" prop="preHandle" label-width="110">
                        <span style="white-space: pre-wrap; word-break: break-all;">{{ form.preHandle || '-' }}</span>
                     </el-form-item>
                  </el-col>
                  <el-col :span="24" v-show="form.preHandleType === 'JAR'">
                     <el-form-item label="前置JAR包" prop="preHandle" label-width="110">
                        <span style="white-space: pre-wrap; word-break: break-all;">
                           {{ form.preHandleJarName || form.preHandleJarUrl }}
                        </span>
                     </el-form-item>
                  </el-col>
                  <el-col :span="24">
                     <el-form-item label="后置处理器类型" prop="postHandleType" label-width="110">
                        {{ form.postHandleType || '无'}}
                     </el-form-item>
                  </el-col>
                  <el-col :span="24" v-show="form.postHandleType === 'GLUE_JAVA'">
                     <el-form-item label="后置处理器" prop="postHandle" label-width="110">
                        <span style="white-space: pre-wrap; word-break: break-all;">{{ form.postHandle || '-' }}</span>
                     </el-form-item>
                  </el-col>
                  <el-col :span="24" v-show="form.postHandleType === 'JAR'">
                     <el-form-item label="后置JAR包" prop="postHandle" label-width="110">
                        <span style="white-space: pre-wrap; word-break: break-all;">
                           {{ form.postHandleJarName || postHandleJarUrl }}
                        </span>
                     </el-form-item>
                  </el-col>
               </el-row>
               <el-row>
                  <el-col :span="9">
                     <el-form-item label="是否缓存结果" prop="isCache" label-width="110">
                        <span v-if="form.isCache === 1">是</span>
                        <span v-if="form.isCache === 0">否</span>
                     </el-form-item>
                  </el-col>
                  <el-col :span="10">
                     <el-form-item label="有效缓存时间" prop="effectiveTime" label-width="auto">
                        {{ form.effectiveTime }}
                        <span v-if="form.timeUnit === 'MINUTES'">分钟</span>
                        <span v-else-if="form.timeUnit === 'HOURS'">小时</span>
                        <span v-else-if="form.timeUnit === 'DAYS'">天</span>
                        <span v-else>-</span>
                     </el-form-item>
                  </el-col>
               </el-row>
               <el-row>
                  <el-col :span="9">
                     <el-form-item label="是否为对象" prop="isObj" label-width="110">
                        <span v-if="form.isObj === 1">是</span>
                        <span v-if="form.isObj === 0">否</span>
                     </el-form-item>
                  </el-col>
                  <el-col :span="15">
                     <el-form-item label="结果集是否作为请求参数" prop="asReqParam" label-width="auto">
                        <span v-if="form.asReqParam === 1">是</span>
                        <span v-if="form.asReqParam === 0">否</span>
                     </el-form-item>
                  </el-col>
               </el-row>
               <el-row>
                  <el-col :span="24">
                     <el-row class="edit-list header" :gutter="10">
                        <el-col :span="2"></el-col>
                        <el-col :span="7" style="text-align: center;">请求字段名</el-col>
                        <el-col :span="6" style="text-align: center;">取值参数名</el-col>
                        <el-col :span="6" style="text-align: center;">固定值</el-col>
                     </el-row>
                     <el-form-item prop="header" label-width="0">
                        <div class="list">
                           <el-row class="edit-list content" :gutter="10" v-for="param, index in form.initParam" :key="index">
                              <el-col :span="3">
                                 <span v-if="index === 0" style="font-weight: bold;">初始参数</span>
                              </el-col>
                              <el-col :span="6">{{ param.sourceField || '-' }}</el-col>
                              <el-col :span="6">{{ param.targetField || '-' }}</el-col>
                              <el-col :span="6">{{ param.value || '-' }}</el-col>
                           </el-row>
                           <el-row class="edit-list content" :gutter="10" v-if="!form.initParam?.length">
                              <el-col :span="3" style="font-weight: bold;">初始参数</el-col>
                              <el-col :span="18" style="color: gray;">暂无数据</el-col>
                           </el-row>
                        </div>
                     </el-form-item>
                  </el-col>
               </el-row>
            </template>
            <!-- step 5 -->
            <template v-if="editStep === 4">
               5
            </template>
         </el-form>
         <template #footer>
            <div class="dialog-footer">
               <el-button v-show="editStep > 0" @click="switchEditStep(editStep - 1)">上一步</el-button>
               <el-button v-show="editStep < 4" type="primary" @click="switchEditStep(editStep + 1)">下一步</el-button>
               <el-button @click="cancel">取 消</el-button>
            </div>
         </template>
      </el-dialog>

      <el-drawer
         v-model="drawer"
         title="数据解析程序包"
         direction="rtl"
         width="80%"
         :before-close="hideDecode"
      >
         <DataDecode :visible="drawer" :id="drawerTargetId" :systemId="drawerTargetSysId" />
   </el-drawer>
   </div>
</template>

<script setup name="Menu">
import { ref } from "vue";
import {
   pullUpdate,
   pullAdd,
   pullGetListByPage,
   pullGetList,
   pullGetDetail,
   pullDelete,
   pullClearCache,
   pullSymbolOptions
} from "@/api/pull";
import { missionGetServerList, missionGetPullList } from "@/api/mission";
import { objectModelGetListByPage } from "@/api/objectModel";
import { dataSystemGetList } from "@/api/dataSystem";
import { dynamicGetTableHead, dynamicGetModelOption } from "@/api/dynamic";
import { dictTypeGetList } from "@/api/dict/type";
import RecursiveItem from '@/components/RecursiveItem'
import DataDecode from './dataDecode.vue'
import { getToken } from "@/utils/auth";
import axios from "axios";
import  * as XLSX from 'xlsx';

const { proxy } = getCurrentInstance();

const menuList = ref([]);
const open = ref(false);
const loading = ref(false);
const showSearch = ref(true);
const title = ref("");
const isExpandAll = ref(false);
const refreshTable = ref(true);
const total = ref(0);

// 取值参数和固定值至少填写一个
const columnDataValidator = (rule, value, callback, row) => {
   if(row.targetField || row.value){
      callback()
   }
   callback(new Error('请输入取值参数名或固定值'))
}

const data = reactive({
   form: {
      systemId: null,
      dynamicTableId: null, // 物模型id
      type: null, // 1--拉取配置，2--服务配置
      name: null,
      description: null,
      pullStrategy: null,
      url: null,
      timeout: null,
      initParam: [],
      uriParam: [],
      header: [],
      bodyTemplate: null,
      returnTemplate: null,
      isLoop: 0,
      loopPath: null,
      pageNo: null,
      respSuccessVal: null,
      respStatus: null,
      respPageCount: null,
      respBody: null,
      sourceDsId: null,
      sourceDb: null,
      selectSql: null,
      fieldCovertMapping: [],
      isObj: null,
      resultKey: null,
      relationKey: null,
      preHandleType: null,
      preHandleJarUrl: null,
      preHandleJarName: null,
      preHandle: null,
      postHandleType: null,
      postHandleJarUrl: null,
      postHandleJarName: null,
      postHandle: null,
      isCache: 0,
      isObj: 0,
      asReqParam: 0,
      effectiveTime: null,
      timeUnit: null,
      limiterFrequency: null,
      limiterUnit: null,
      filterGroups: [],
   },
   queryParams: {
      pageNum: 1,
      pageSize: 10,
      keyword: null,
      systemId: null,
      type: null
   },
   detail: {},
   rules: {
      name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
      code: [{ required: true, message: "编码不能为空", trigger: "blur" }],
      type: [{ required: true, message: "请选择接口类型", trigger: "change" }],
      systemId: [{ required: true, message: "请选项所属系统", trigger: "change" }],
      url: [{ required: true, message: "请输入URL", trigger: "blur" }],
      pullStrategy: [{ required: true, message: "请选择拉取方式", trigger: "change" }],
      // dynamicTableId: [{ required: true, message: "请选择物模型", trigger: "blur" }],
      resultKey: [{ required: true, message: "请输入结果集存储Key", trigger: "change" }],
      category: [{ required: true, message: "请输入类型", trigger: "change" }],
      modelSourceField: [{ required: true, message: "请输入字段", trigger: "blur" }],
      columnSourceField: [{ required: true, message: "请输入请求字段名", trigger: "blur" }],
      inputVal: [{ required: true, message: "请输入值", trigger: "blur" }],
      chooseRule: [{ required: true, message: "请选择规则", trigger: "blur" }]
   }
});

const { queryParams, form, detail, rules } = toRefs(data);

const dataSystemOptions = ref([]);
/** 获取系统选项 */
function getDataSystemOption() {
   dataSystemGetList().then(response => {
      dataSystemOptions.value = response.data;
   });
}

const objectModelOptions = ref([]);
/** 获取模型选项 */
function getObjectModelOption() {
   dynamicGetModelOption().then(response => {
      objectModelOptions.value = response.data;
      if(form.value.dynamicTableId){
         getModelFeatureOption();
      }
   });
}
const symbolOptions = ref([]);
function getPullSymbolOptions() {
   pullSymbolOptions().then(response => {
      symbolOptions.value = response.data;
   });
}

// 手动切换系统
function handleSystemChange(){
   form.value.dynamicTableId = null;
}

// 系统变化
watch(() => form.value.systemId, val => {
   modelFeatureOptions.value = [];
   if(val) {
      getObjectModelOption()
      getDictTypeOption()
   }
})

// 手动物模型
function handleModelChange(){
   form.value.fieldCovertMapping.forEach(e => {
      e.targetField = null
      e.dicTypeId = null
   })
}

// 物模型变化
watch(() => form.value.dynamicTableId, val => {
   if(val) getModelFeatureOption();
})

// 物模型转换
const modelFeatureOptions = ref([]);
/** 获取模型属性选项 */
function getModelFeatureOption() {
   if(form.value.systemId && form.value.dynamicTableId){
      dynamicGetTableHead({
         systemId: form.value.systemId,
         tableId: form.value.dynamicTableId
      }).then(response => {
         modelFeatureOptions.value = response.data;
         // 自动匹配字段对应物模型属性
         form.value.fieldCovertMapping.forEach(e => {
            const feature = response.data.find(feat => feat.name === e.targetField)
         })
      });
   }
}

// 模型属性变化重置字典类型
function modelFeatureChange(index){
   form.value.fieldCovertMapping[index].dicTypeId = null
}

// 物模型转换
const dictTypeOptions = ref([]);
/** 获取模型属性选项 */
function getDictTypeOption() {
   if(form.value.systemId && form.value.dynamicTableId){
      dictTypeGetList({ systemId: form.value.systemId }).then(response => {
         dictTypeOptions.value = response.data;
      });
   }
}

// 根据模型属性名判断是不是字典类型
function isFeatDict(name){
   const targetType = modelFeatureOptions.value.find(feat => feat.name === name)?.category
   return targetType === 2
}

/** 查询系统列表 */
function getList() {
   loading.value = true;
   pullGetListByPage(queryParams.value).then(response => {
      menuList.value = response.data.records;
      total.value = response.data.total;
      loading.value = false;
   }).catch(()=>{
      proxy.$modal.msgError("获取列表数据失败");
      loading.value = false;
   });
}

function getSystemNameById(id) {
   return dataSystemOptions.value.find(item => item.id === +id)?.name || '-'
}

/** 表单重置 */
function reset() {
   form.value = {
      systemId: null,
      dynamicTableId: null, // 物模型id
      type: null, // 1--拉取配置，2--服务配置
      name: null,
      description: null,
      pullStrategy: null,
      url: null,
      timeout: null,
      initParam: [],
      uriParam: [],
      header: [],
      bodyTemplate: null,
      returnTemplate: null,
      isLoop: 0,
      loopPath: null,
      pageNo: null,
      respSuccessVal: null,
      respStatus: null,
      respPageCount: null,
      respBody: null,
      sourceDsId: null,
      sourceDb: null,
      selectSql: null,
      fieldCovertMapping: [],
      isObj: null,
      resultKey: null,
      relationKey: null,
      preHandleType: null,
      preHandleJarUrl: null,
      preHandleJarName: null,
      preHandle: null,
      postHandleType: null,
      postHandleJarUrl: null,
      postHandleJarName: null,
      postHandle: null,
      isCache: 0,
      isObj: 0,
      asReqParam: 0,
      effectiveTime: null,
      timeUnit: null,
      limiterFrequency: null,
      limiterUnit: null,
      filterGroups: []
   };
   editTargetId.value = null;
   editStep.value = 0;
   reqJsonObj.value = null;
   resJsonObj.value = null;
   detail.value = {};
   proxy.resetForm("editRef");
}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.value.pageNum = 1;
  getList();
}

/** 重置按钮操作 */
function resetQuery() {
  proxy.resetForm("queryRef");
  handleQuery();
}

const openDetail = ref(false);
function handleView(row){
   reset();
   openDetail.value = true;
   pullGetDetail({id: row.id}).then(response => {
      form.value = {
         ...response.data,
         uriParam: response.data.uriParam || [],
         initParam: response.data.initParam || [],
         header: response.data.header || [],
         fieldCovertMapping: response.data.fieldCovertMapping || [],
         filterGroups: response.data.filterGroups || [],
      }
      reqJsonObj.value = JSON.parse(response?.data?.bodyTemplate || "{}")
      resJsonObj.value = JSON.parse(response?.data?.returnTemplate || "{}")
      getObjectModelOption();
      getDictTypeOption();
   });
}

/** 新增按钮操作 */
function handleAdd() {
   reset();
   loadTempData();
   getObjectModelOption()
   open.value = true;
   title.value = "新增接口";
}

const editTargetId = ref(null)
/** 修改按钮操作 */
async function handleUpdate(row) {
   reset();
   editTargetId.value = row.id
   pullGetDetail({id: row.id}).then(response => {
      form.value = {
         ...response.data,
         uriParam: response.data.uriParam || [],
         initParam: response.data.initParam || [],
         header: response.data.header || [],
         fieldCovertMapping: response.data.fieldCovertMapping || [],
         filterGroups: response.data.filterGroups || [],
      }
      reqJsonObj.value = JSON.parse(response?.data?.bodyTemplate || "{}")
      resJsonObj.value = JSON.parse(response?.data?.returnTemplate || "{}")
      open.value = true;
      title.value = "修改接口";
      getObjectModelOption();
   });
}

// 切换步骤
const editStep = ref(0);
function switchEditStep(num){
   if(openDetail.value){
      editStep.value = num
      return
   }
   proxy.$refs["editRef"].validate(valid => {
      if (valid) {
         if(!reqJsonValid.value){
            proxy.$modal.msgError("请求体格式错误")
            return
         }
         if(!resJsonValid.value){
            proxy.$modal.msgError("返回体格式错误")
            return
         }
         editStep.value = num
      }
   });
}

function toggleParam(type, index, target){
   const templateData = {
      sourceField: null,
      targetField: null,
      value: null
   }
   if(type == 'minus'){
      switch(target){
         case 'header':
            form.value['header'].splice(index, 1)
            break
         case 'uri':
            form.value['uriParam'].splice(index, 1)
            break
         case 'init':
            form.value['initParam'].splice(index, 1)
            break
      }
   }else if(type == 'add'){
      switch(target){
         case 'header':
            form.value['header'].push(templateData)
            break
         case 'uri':
            form.value['uriParam'].push(templateData)
            break
         case 'init':
            form.value['initParam'].push(templateData)
            break
      }
   }
}

function toggleObject(type, index){
   const objectData = {
      sourceField: null,
      targetField: null,
      save: null,
      unique: null,
      dicTypeId: null
   }
   if(type == 'minus'){
      form.value['fieldCovertMapping'].splice(index, 1)
   }else if(type == 'add'){
      form.value['fieldCovertMapping'].push(objectData)
   }
}

// 添加删除
function toggleConfig(target ,type, index, items, level = 0){
   if(type == 'minus'){
        items.splice(index, 1)
   }else if(type == 'add'){
      if(!items){
         items = [{
            type: null,
            sourceField: null,
            targetField: null,
            value: null,
            child: []
         }]
         return
      }
      items.push({
         type: null,
         sourceField: null,
         targetField: null,
         value: null,
         child: []
      })
   }
}

// 修改类型
function toggleConfigType(item, type){
   if(item.type == 2 && item.child?.length === 0){
      item.child = new Array(1).fill({
         type: null,
         sourceField: null,
         targetField: null,
         value: null,
         child: []
      })
   }
}

// 请求体/响应体JSON编辑
import JsonEditorVue from 'json-editor-vue3';
const reqJsonObj = ref({});
const reqJsonValid = ref(true);
const resJsonObj = ref({});
const resJsonValid = ref(true);
const jsonEditorOptions = ref({
  search: false,
  history: false,
  enableTransform: false,
  enableSort: false
})
const jsonEditorUpdate = (type) => {
   if(type === 'req'){
      reqJsonValid.value = true
      let newJsonStr = JSON.stringify(reqJsonObj.value);
      if (form.value.bodyTemplate !== newJsonStr) {
         form.value.bodyTemplate = newJsonStr
      }
   }
   if(type === 'res'){
      resJsonValid.value = true
      let newJsonStr = JSON.stringify(resJsonObj.value);
      if (form.value.returnTemplate !== newJsonStr) {
         form.value.returnTemplate = newJsonStr
      }
   }
}

// 格式错误
const jsonEditorError = (editor, err, type) => {
   if(err?.length && type === 'req'){
      reqJsonValid.value = false
   }
   if(err?.length & type === 'res'){
      resJsonValid.value = false
   }
}

// 物模型导入字段
const uploading = ref(false);
const fileUpload = ref(null)
const importFile = async (file) => {
   fileUpload.value.clearFiles()
   uploading.value = true;
   const formData = new FormData();
   formData.append("file", file.raw);
   const res = await axios.post(import.meta.env.VITE_APP_BASE_API + "/pull/config/excel/parse", formData, {
      headers: {
         "Content-Type": "multipart/form-data",
         Authorization: "Bearer " + getToken()
      },
   });

   if (res.data.code === 200) {
      proxy.$modal.msgSuccess('导入成功');
      const newArr = res.data.data.map(e => {
         // 在选项中查找是否存在
         const feature = (modelFeatureOptions.value || []).find(feat => feat.name === e.targetField)
         return {
            sourceField: e.sourceField,
            targetField: feature?.name || null,
            save: null,
            unique: null,
            dicTypeId: null
         }
      });
      form.value.fieldCovertMapping = [ ...form.value.fieldCovertMapping, ...newArr ]
   } else {
      proxy.$modal.msgError(res.data.msg);
   }
   uploading.value = false;
};


// 下载接口物模型导入模板
const downloadTemplate = () => {
      const data = [
      ['字段', '物模型属性'],
      ['q', 'a'],
      ['w', 'b'],
      ['e', 'c'],
      ['r', 'd'],
   ]
   const ws = XLSX.utils.aoa_to_sheet(data);
   const wb = XLSX.utils.book_new();
   XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
   XLSX.writeFile(wb, '接口配置字段与物模型属性.xlsx');
}

// 修改前后置处理器类型
function handleTypeChange(type) {
   if(type === 'pre'){
      form.value.preHandleJarUrl = null
      form.value.preHandleJarName = null
      form.value.preHandle = null
   }
   if(type === 'post'){
      form.value.postHandleJarUrl = null
      form.value.postHandleJarName = null
      form.value.postHandle = null
   }
}

// jar文件上传
const preHandleUploading = ref(false);
const preHandleFileUpload = ref(null);
const postHandleUploading = ref(false);
const postHandleFileUpload = ref(null);
const importJarFile = async (file, type) => {
   if(type === 'pre'){
      preHandleFileUpload.value.clearFiles()
      preHandleUploading.value = true;
   } else {
      postHandleFileUpload.value.clearFiles()
      postHandleUploading.value = true;
   }
   const formData = new FormData();
   formData.append("file", file.raw);
   const res = await axios.post(import.meta.env.VITE_APP_BASE_API + "/file/upload", formData, {
      headers: {
         "Content-Type": "multipart/form-data",
         Authorization: "Bearer " + getToken()
      },
   });

   if(res.data.code === 200 && res.data.data) {
      proxy.$modal.msgSuccess('导入成功');
      if(type === 'pre'){
         form.value.preHandleJarUrl = res.data.data.path;
         form.value.preHandleJarName = res.data.data.name;
      } else {
         form.value.postHandleJarUrl = res.data.data.path;
         form.value.postHandleJarName = res.data.data.name;
      }
   } else {
      proxy.$modal.msgError(res.data.msg);
   }

   if(type === 'pre'){
      preHandleFileUpload.value.clearFiles()
      preHandleUploading.value = false;
   } else {
      postHandleFileUpload.value.clearFiles()
      postHandleUploading.value = false;
   }
};

function toggleRule(type, index, i){
   const ruleData = {
      fieldName: null,
      inputVal: null,
      operate: null,
      symbolDicId: null
   }
   const groupData = {
      filterRules: [ ruleData ],
      operate: null
   }
   if(type == 'minus'){
      if(typeof i === 'number'){
         if(form.value['filterGroups'][index]['filterRules'].length === 1){
            form.value['filterGroups'].splice(index, 1)
            return
         }
         form.value['filterGroups'][index]['filterRules'].splice(index, 1)
         return
      }
      form.value['filterGroups'].splice(index, 1)
   }else if(type == 'add'){
      if(typeof i === 'number'){
         form.value['filterGroups'][index]['filterRules'].push(ruleData)
         return
      }
      form.value['filterGroups'].push(groupData)
   }
}

/** 提交按钮 */
function submitForm() {
   proxy.$refs["editRef"].validate(valid => {
      if (valid) {
         if(!reqJsonValid.value){
            proxy.$modal.msgError("请求体格式错误")
            return
         }
         if(!resJsonValid.value){
            proxy.$modal.msgError("返回体格式错误")
            return
         }
         if (editTargetId.value) {
            pullUpdate({ ...form.value, id: editTargetId.value }).then(response => {
               proxy.$modal.msgSuccess("修改成功");
               open.value = false;
               editTargetId.value = null;
               getList();
            });
         } else {
            pullAdd(form.value).then(response => {
               proxy.$modal.msgSuccess("新增成功");
               open.value = false;
               getList();
            });
         }
      }
   });
}

function saveTemp(){
   proxy.$modal.confirm('是否保存当前填写的内容为草稿').then(function () {
      localStorage.pullTempData = JSON.stringify(form.value)
      proxy.$modal.msgSuccess("草稿保存成功");
   }).catch(() => {});
}

/** 取消按钮 */
async function cancel() {
   open.value = false;
   openDetail.value = false;
   reset();
}

// 加载草稿配置
function loadTempData() {
   if(!localStorage.pullTempData) return
   const tempData = JSON.parse(localStorage.pullTempData)
   tempData.id = null
   tempData.uriParam = tempData.uriParam || []
   tempData.initParam = tempData.initParam || []
   tempData.header = tempData.header || []
   tempData.fieldCovertMapping = tempData.fieldCovertMapping || [],
   tempData.filterGroups = tempData.filterGroups || [],
   proxy.$modal.confirm('是否加载上次保存的草稿?').then(() => {
      form.value = tempData
      reqJsonObj.value = JSON.parse(tempData.bodyTemplate || "{}")
      resJsonObj.value = JSON.parse(tempData.returnTemplate || "{}")
      proxy.$modal.msgSuccess("读取草稿成功");
   }).catch(() => {})
}

/** 删除按钮操作 */
function handleDelete(row) {
   proxy.$modal.confirm('是否确认删除名称为"' + row.name + '"的数据项?').then(function () {
      return pullDelete({ ids: row.id });
   }).then(() => {
      getList();
      proxy.$modal.msgSuccess("删除成功");
   }).catch(() => { });
}

const selectedList = ref([])
function handleSelectionChange(list) {
   selectedList.value = list
}

/** 多选删除操作 */
function handleDeleteBatch() {
   if (selectedList.value.length) {
      proxy.$modal.confirm('是否确认删除选中的' + selectedList.value.length + '个数据?').then(function () {
         const ids = selectedList.value.map(item => item.id).join(',');
         return pullDelete({ ids });
      }).then(() => {
         getList();
         proxy.$modal.msgSuccess("删除成功");
      }).catch(() => { });
   } else {
      proxy.$modal.msgError("请选择要删除的数据");
   }
}
// 解析包抽屉
const drawer = ref(false);
const drawerTargetId = ref(null);
const drawerTargetSysId = ref(null);
function viewDecode(id, systemId) {
   drawerTargetId.value = id;
   drawerTargetSysId.value = systemId;
   drawer.value = true;
}
function hideDecode() {
   drawerTargetId.value = null;
   drawerTargetSysId.value = null;
   drawer.value = false;
}

// 清理缓存
function clearCache(row){
   if(!row.systemId){
      proxy.$modal.msgError("缺少所属系统信息");
      return
   }
   pullClearCache({ systemId: row.systemId, configId: row.id }).then(response => {
      proxy.$modal.msgSuccess("清理缓存成功");
   }).catch(() => {
      proxy.$modal.msgError("清理缓存失败");
   });
}

getList();
getDataSystemOption();
getPullSymbolOptions();
</script>
<style lang='scss' scoped>
   .list{
      width: 100%;
      margin-bottom: 10px;
      :deep(.el-form-item__content){
         margin-left: 0 !important;
         .el-row{
            width: 100%;
         }
      }
      &.model{
         max-height: 360px;
         overflow-y: overlay;
         overflow-x: hidden;
      }
      &.rule-group{
         max-height: 600px;
         overflow-y: overlay;
         overflow-x: hidden;
      }
   }
   :deep(.el-row.edit-list){
      > .el-col{
         height: 50px;
         display: flex;
         align-items: center;
         justify-content: center;
      }
   }
   :deep(.el-drawer){
      width: 80% !important;
   }
   .note{
      padding: 10px 30px;
      color: rgb(160, 160, 160);
   }
   .filter-group{
      display: flex;
      .filter-rule{
         flex: 1;
         border: 1px solid rgb(218, 218, 218);
         margin-bottom: 10px;
         border-radius: 6px;
         overflow: hidden;
         .el-row:first-of-type{
            margin-top: 18px;
         }
      }
   }
   .mid-operate{
      margin: 0 auto;
      padding-top: 8px;
      width: 100px;
   }
   .filter-group-btn{
      width: 80px;
      display: flex;
      align-items: center;
      justify-content: flex-start;
      margin-bottom: 10px;
      margin-left: 20px;
      .el-button{
         border: 1px solid;
         padding: 8px;
         border-radius: 50%;
         &:hover{
            border: 1px solid;
         }
      }
   }
   </style>